package com.astrob.tspant;

import java.util.ArrayList;


public class Tsp {
    //蚂蚁数组
    public Ant[] m_antAry = new Ant[PublicFun.getInstance().N_ANT_COUNT];//50 蚂蚁数量
//    public Ant[] m_betterAnts = new Ant[PublicFun.getInstance().N_IT_COUNT];//200迭代次数 定义一组蚂蚁,用来保存每一次搜索中较优结果,不参与搜索
    public Ant m_bestAnt;//定义一个蚂蚁变量,用来保存最终最优结果,不参与搜索

    public ArrayList<Ant> m_betterAnts = new ArrayList<Ant>();

    /*
     * 初始化数据
     */
    public void InitData() throws CloneNotSupportedException {

        PublicFun.getInstance().ABPathList.clear();
        if (PublicFun.getInstance().cityList.size() > 1) {
            PublicFun.getInstance().N_CITY_COUNT = PublicFun.getInstance().cityList.size();

            PublicFun.getInstance().Distance = new double[PublicFun.getInstance().N_CITY_COUNT][PublicFun.getInstance().N_CITY_COUNT];//15 城市数量

            //两两城市间的信息量
            PublicFun.getInstance().Trial = new double[PublicFun.getInstance().N_CITY_COUNT][PublicFun.getInstance().N_CITY_COUNT];

            m_bestAnt = new Ant();
            for (int i = 0; i < PublicFun.getInstance().N_ANT_COUNT; i++) {
                m_antAry[i] = new Ant();
            }

            //先把最优蚂蚁的路径长度设置为一个很大值
            m_bestAnt.m_dbPathLength = PublicFun.getInstance().DB_MAX;

            //初始化矩阵；两城市之间的距离
            PublicFun.getInstance().crearABPath();


        } else {
            // 原test；理论上进不来
            //初始化所有蚂蚁
            //两两城市间的距离
            PublicFun.getInstance().Distance = new double[PublicFun.getInstance().N_CITY_COUNT][PublicFun.getInstance().N_CITY_COUNT];//15 城市数量

            //两两城市间的信息量
            PublicFun.getInstance().Trial = new double[PublicFun.getInstance().N_CITY_COUNT][PublicFun.getInstance().N_CITY_COUNT];

            m_bestAnt = new Ant();
            for (int i = 0; i < PublicFun.getInstance().N_ANT_COUNT; i++) {
                m_antAry[i] = new Ant();
            }

            //先把最优蚂蚁的路径长度设置为一个很大值
            m_bestAnt.m_dbPathLength = PublicFun.getInstance().DB_MAX;

            //初始化矩阵；两城市之间的距离
            for (int i = 0; i < PublicFun.getInstance().N_CITY_COUNT; i++) {
                for (int j = i; j < PublicFun.getInstance().N_CITY_COUNT; j++) {
                    if (i == j)
                        PublicFun.getInstance().Distance[i][j] = 0.0;//同一个城市为0
                    else {
                        PublicFun.getInstance().Distance[i][j] = (j - i) * 100;//i-j的距离与j-i的距离相等
                        PublicFun.getInstance().Distance[j][i] = PublicFun.getInstance().Distance[i][j];
                    }
                }
            }
        }


        //初始化信息素
        for (int i = 0; i < PublicFun.getInstance().N_CITY_COUNT; i++) {
            for (int j = 0; j < PublicFun.getInstance().N_CITY_COUNT; j++) {
                PublicFun.getInstance().Trial[i][j] = 1.0;
            }
        }

        Iterator();//开始迭代

    }

    /*
     * 更新环境信息素
     */

    public void UpdateTrial() {
        //临时数组,保存各只蚂蚁在两两城市间新留下的信息素
        double[][] dbTempAry = new double[PublicFun.getInstance().N_CITY_COUNT][PublicFun.getInstance().N_CITY_COUNT];

        //全部设置为0;
        for (int i = 0; i < PublicFun.getInstance().N_CITY_COUNT; i++) {
            for (int j = 0; j < PublicFun.getInstance().N_CITY_COUNT; j++) {
                dbTempAry[i][j] = 0.0;
            }
        }
        //计算新增加的信息素,保存到临时变量
        int m = 0;
        int n = 0;
        for (int i = 0; i < PublicFun.getInstance().N_ANT_COUNT; i++) {
            for (int j = 1; j < PublicFun.getInstance().N_CITY_COUNT; j++) {
                m = m_antAry[i].m_nPath[j];
                n = m_antAry[i].m_nPath[j - 1];
                dbTempAry[n][m] = dbTempAry[n][m] + PublicFun.getInstance().DBQ / m_antAry[i].m_dbPathLength;
                dbTempAry[m][n] = dbTempAry[n][m];
            }

            //最后城市与开始城市之间的信息素
            n = m_antAry[i].m_nPath[0];
            dbTempAry[n][m] = dbTempAry[n][m] + PublicFun.getInstance().DBQ / m_antAry[i].m_dbPathLength;
            dbTempAry[m][n] = dbTempAry[n][m];
        }

        //更新环境信息素
        for (int i = 0; i < PublicFun.getInstance().N_CITY_COUNT; i++) {
            for (int j = 0; j < PublicFun.getInstance().N_CITY_COUNT; j++) {
                //最新的环境信息素 = 留存的信息素 + 新留下的信息素
                PublicFun.getInstance().Trial[i][j] = PublicFun.getInstance().Trial[i][j] * PublicFun.getInstance().ROU + dbTempAry[i][j];
            }
        }
    }


    /*
     * 迭代
     */
    public void Iterator() throws CloneNotSupportedException {
        //迭代次数内进行循环
        m_betterAnts.clear();
        for (int i = 0; i < PublicFun.getInstance().N_IT_COUNT; i++) {
            //每只蚂蚁搜索一遍
            double minLength = PublicFun.getInstance().DB_MAX;
            int m = 0;
            for (int j = 0; j < PublicFun.getInstance().N_ANT_COUNT; j++) {
                m_antAry[j].Search();
                if (minLength > m_antAry[j].m_dbPathLength) {
                    minLength = m_antAry[j].m_dbPathLength;
                    m = j;
                }
            }

            //保存较优结果
            m_betterAnts.add((Ant) m_antAry[m].clone());//m_nPath clone失败地址不变
            UpdateTrial();

//            m_betterAnts.get(i).printPath(i + " --------");

        }

        //找出最优蚂蚁
        double minLength = PublicFun.getInstance().DB_MAX;
        int m = 0;
        for (int k = 0; k < PublicFun.getInstance().N_IT_COUNT; k++) {
            if (minLength > m_betterAnts.get(k).m_dbPathLength) {
                minLength = m_betterAnts.get(k).m_dbPathLength;
                m = k;
            }
        }
        m_bestAnt = m_betterAnts.get(m);
//        m_bestAnt.printPath("~~~~~~~~~");

//        getBetterAnt();//输出每次的较优路径
//        getBestAnt();//输出最佳路径

    }

    /*
     * 输出最佳路径到控制台.(暂不使用,但保留)
     */
    public void getBestAnt() {
        System.out.println("最佳路径:");
        System.out.println("路径:" + getAntPath(m_bestAnt) + "长度:" + getAntLength(m_bestAnt));
    }

    /*
     * 输出每次的较优路径到控制台.(暂不使用,但保留)
     */
    public void getBetterAnt() {
        System.out.println("每一次的较优路径:");
        for (int i = 0; i < m_betterAnts.size(); i++) {
            System.out.println("(" + i + ") 路径:" + getAntPath(m_betterAnts.get(i)) + "长度:" + getAntLength(m_betterAnts.get(i)));
        }
    }

    /*
     * 返回蚂蚁经过的路径
     */
    public String getAntPath(Ant ant) {
        String s = "";
        for (int i = 0; i < ant.m_nPath.length; i++) {
            s += ant.m_nPath[i] + "-";
        }

        s += "E";

        return s;
    }

    /*
     * 返回蚂蚁经过的长度
     */
    public double getAntLength(Ant ant) {
        return ant.m_dbPathLength;
    }


}
